package com.zoe.thread.th01_复习;

/**
 * @program: hellojava8
 * @description: 使用同步方法解决 线程安全问题
 * @author: Dawson.Zhang
 * @create: 2019-11-19
 **/
class Window3 implements Runnable {
    private Integer tiket = 100;
    private boolean flog = true;

    /**
     *
     *   synchronized(同步监视器){
     *      //需要被同步的代码
     *
     *   }
     *  说明：1.操作共享数据的代码，即为需要被同步的代码。  -->不能包含代码多了，也不能包含代码少了。
     *       2.共享数据：多个线程共同操作的变量。比如：ticket就是共享数据。
     *       3.同步监视器，俗称：锁。任何一个类的对象，都可以充当锁。
     *          要求：多个线程必须要共用同一把锁。
     *
     * 补充：在实现Runnable接口创建多线程的方式中，我们可以考虑使用this充当同步监视器。
     * 在继承Thread类创建多线程的方式中，慎用this充当同步监视器，考虑使用当前Class类充当同步监视器。
     *
     * 如果synchronized加在一个类的普通方法上，那么相当于synchronized(this)。
     *
     * 如果synchronized加载一个类的静态方法上，那么相当于synchronized(Class对象)。
     */
    public synchronized void show() {
        if (tiket > 0) {
            try {
                Thread.currentThread().sleep(0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "----卖出的火车票号为----" + tiket);
            tiket--;
        }else{
            flog=false;
        }
    }

    @Override
    public void run() {
        while (flog) {
            show();
        }
    }
}

public class WindowTest3 {
    public static void main(String[] args) {
        Window3 w = new Window3();
        Thread thread1 = new Thread(w);
        thread1.setName("窗口1");
        thread1.start();
        Thread thread2 = new Thread(w);
        thread2.setName("窗口2");
        thread2.start();
        Thread thread3 = new Thread(w);
        thread3.setName("窗口3");
        thread3.start();
    }
}
